/*******************************************************************************
 * Copyright (c) 2011 Erik Byström.
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 ******************************************************************************/
package se.slackers.automatunes.ui;

import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSeparator;

import se.slackers.automatunes.ApplicationManager;
import se.slackers.automatunes.algorithm.AudioRule;

/**
 * @author Erik Byström
 * 
 */
@SuppressWarnings("serial")
public class AutomataJFrame extends JFrame {
	private static final String UPDATE_INTERVAL = "Update (ms)";

	private static final String PLAY = "Play";
	private static final String PAUSE = "Pause";

	private final ApplicationManager manager;
	private final AutomataJPanel panel;
	private final AudioRule audioRule;
	private final ParameterSet parameters = new ParameterSet();

	private Thread thread;

	public AutomataJFrame(final ApplicationManager manager, final String title) {
		super(title);
		this.manager = manager;
		this.panel = manager.createDefaultAutomataPanel();
		this.audioRule = manager.createDefaultAudioRule();

		// Setup local parameters
		parameters.add(new IntParameter(UPDATE_INTERVAL, 200, 10, 10000)
				.tooltip("Rule update interval in milliseconds"));

		// build UI
		buildMenu();

		final JPanel sidePanel = new JPanel(new VerticalFlowLayout(VerticalFlowLayout.TOP, 5, 5));
		// final JPanel sidePanel = new JPanel(new GridLayout(1, 3));
		final JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 5, 5));

		final JButton play = new JButton(PLAY);
		play.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(final ActionEvent e) {
				if (PLAY == play.getText()) {
					play.setText(PAUSE);
					start();
				} else {
					play.setText(PLAY);
					stop();
				}
			}
		});
		buttonPanel.add(play);

		final ParameterSet localParameters = new ParameterSet(parameters);
		localParameters.chain(audioRule.parameters());

		sidePanel.add(new ParameterJPanel("Global").display(manager.globalParameters()));
		sidePanel.add(new ParameterJPanel("Field").display(localParameters));
		sidePanel.add(new ParameterJPanel("Rule").display(panel.rule().parameters()));

		// sidePanel.setPreferredSize(new Dimension(200, panel.getPreferredSize().height));
		getContentPane().add(panel, BorderLayout.CENTER);
		getContentPane().add(new JScrollPane(sidePanel), BorderLayout.EAST);
		getContentPane().add(buttonPanel, BorderLayout.SOUTH);

		pack();

		this.addWindowListener(new WindowAdapter() {
			@Override
			public void windowClosed(final WindowEvent arg0) {
				stop();
			}
		});
	}

	/**
	 * Builds and connects the default menu
	 */
	private void buildMenu() {
		final JMenuBar menu = new JMenuBar();
		final JMenu control = new JMenu("Control");
		final JMenuItem automata = new JMenuItem("New automata");
		final JMenuItem clear = new JMenuItem("Clear");
		final JMenuItem quit = new JMenuItem("Quit");
		control.add(automata);
		control.add(clear);
		control.add(new JSeparator());
		control.add(quit);
		menu.add(control);
		setJMenuBar(menu);

		clear.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(final ActionEvent e) {
				panel.clear();
				panel.repaint();
			}
		});

		automata.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(final ActionEvent e) {
				manager.createFrame();
			}
		});

		quit.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(final ActionEvent e) {
				manager.shutdown();
			}
		});
	}

	public void start() {
		thread = new Thread(new Runnable() {
			@Override
			public void run() {
				try {
					while (true) {
						panel.step();
						panel.repaint();
						Thread.sleep(parameters.getInt(UPDATE_INTERVAL));
					}
				} catch (final InterruptedException e) {
					System.out.println("Exit " + getTitle());
				}
			}
		}, "Thread " + getTitle());
		thread.start();
	}

	public void stop() {
		if (thread != null) {
			thread.interrupt();
			thread = null;
		}
	}

	public AudioRule audioRule() {
		return audioRule;
	}

	public AutomataJPanel panel() {
		return panel;
	}
}
